package com.zhiwei.most.views

import android.content.Context
import android.graphics.RectF
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.util.AttributeSet
import android.view.View
import androidx.annotation.IntRange
import com.zhiwei.most.R

/**
 * <pre>
 *     author: Blankj
 *     blog  : http://blankj.com
 *     time  : 2017/07/10
 *     desc  :
 * </pre>
 *
 * Convert Kotlin by zhiweizhu on 2022/2/26
 */
class ProgressRing @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {


    private val progressStartColor: Int
    private val progressEndColor: Int
    private val bgStartColor: Int
    private val bgMidColor: Int
    private val bgEndColor: Int
    private var progress: Int
    private val progressWidth: Float
    private val startAngle: Int
    private val sweepAngle: Int
    private val showAnim: Boolean
    private var mMeasureHeight = 0
    private var mMeasureWidth = 0
    private val bgPaint = Paint(Paint.ANTI_ALIAS_FLAG or Paint.DITHER_FLAG)
    private val progressPaint = Paint(Paint.ANTI_ALIAS_FLAG or Paint.DITHER_FLAG)
    private var pRectF: RectF? = null
    private val unitAngle: Float
    private var curProgress = 0

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        mMeasureWidth = measuredWidth
        mMeasureHeight = measuredHeight
        if (pRectF == null) {
            val halfProgressWidth = progressWidth / 2
            pRectF = RectF(
                halfProgressWidth + paddingLeft,
                halfProgressWidth + paddingTop,
                mMeasureWidth - halfProgressWidth - paddingRight,
                mMeasureHeight - halfProgressWidth - paddingBottom
            )
        }
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        if (!showAnim) {
            curProgress = progress
        }
        drawBg(canvas)
        drawProgress(canvas)
        if (curProgress < progress) {
            curProgress++
            postInvalidate()
        }
    }

    // 只需要画进度之外的背景即可
    private fun drawBg(canvas: Canvas) {
        val halfSweep = (sweepAngle / 2).toFloat()
        var i = sweepAngle
        val st = (curProgress * unitAngle).toInt()
        while (i > st) {
            if (i - halfSweep > 0) {
                bgPaint.color = getGradient((i - halfSweep) / halfSweep, bgMidColor, bgEndColor)
            } else {
                bgPaint.color = getGradient((halfSweep - i) / halfSweep, bgMidColor, bgStartColor)
            }
            canvas.drawArc(
                pRectF!!, (
                        startAngle + i).toFloat(), 1f,
                false,
                bgPaint
            )
            --i
        }
    }

    private fun drawProgress(canvas: Canvas) {
        var i = 0
        val end = (curProgress * unitAngle).toInt()
        while (i <= end) {
            progressPaint.color =
                getGradient(i / end.toFloat(), progressStartColor, progressEndColor)
            canvas.drawArc(
                pRectF!!, (
                        startAngle + i).toFloat(), 1f,
                false,
                progressPaint
            )
            i++
        }
    }

    fun setProgress(@IntRange(from = 0, to = 100) progress: Int) {
        this.progress = progress
        invalidate()
    }

    fun getProgress(): Int {
        return progress
    }

    fun getGradient(fractionValue: Float, startColor: Int, endColor: Int): Int {
        var fraction = fractionValue
        if (fraction > 1) fraction = 1f
        val alphaStart = Color.alpha(startColor)
        val redStart = Color.red(startColor)
        val blueStart = Color.blue(startColor)
        val greenStart = Color.green(startColor)
        val alphaEnd = Color.alpha(endColor)
        val redEnd = Color.red(endColor)
        val blueEnd = Color.blue(endColor)
        val greenEnd = Color.green(endColor)
        val alphaDifference = alphaEnd - alphaStart
        val redDifference = redEnd - redStart
        val blueDifference = blueEnd - blueStart
        val greenDifference = greenEnd - greenStart
        val alphaCurrent = (alphaStart + fraction * alphaDifference).toInt()
        val redCurrent = (redStart + fraction * redDifference).toInt()
        val blueCurrent = (blueStart + fraction * blueDifference).toInt()
        val greenCurrent = (greenStart + fraction * greenDifference).toInt()
        return Color.argb(alphaCurrent, redCurrent, greenCurrent, blueCurrent)
    }

    init {
        val ta = context.obtainStyledAttributes(attrs, R.styleable.ProgressRing)
        progressStartColor =
            ta.getColor(R.styleable.ProgressRing_pr_progress_start_color, Color.YELLOW)
        progressEndColor =
            ta.getColor(R.styleable.ProgressRing_pr_progress_end_color, progressStartColor)
        bgStartColor = ta.getColor(R.styleable.ProgressRing_pr_bg_start_color, Color.LTGRAY)
        bgMidColor = ta.getColor(R.styleable.ProgressRing_pr_bg_mid_color, bgStartColor)
        bgEndColor = ta.getColor(R.styleable.ProgressRing_pr_bg_end_color, bgStartColor)
        progress = ta.getInt(R.styleable.ProgressRing_pr_progress, 0)
        progressWidth = ta.getDimension(R.styleable.ProgressRing_pr_progress_width, 8f)
        startAngle = ta.getInt(R.styleable.ProgressRing_pr_start_angle, 150)
        sweepAngle = ta.getInt(R.styleable.ProgressRing_pr_sweep_angle, 240)
        showAnim = ta.getBoolean(R.styleable.ProgressRing_pr_show_anim, true)
        ta.recycle()
        unitAngle = (sweepAngle / 100.0).toFloat()
        bgPaint.style = Paint.Style.STROKE
        bgPaint.strokeCap = Paint.Cap.ROUND
        bgPaint.strokeWidth = progressWidth
        progressPaint.style = Paint.Style.STROKE
        progressPaint.strokeCap = Paint.Cap.ROUND
        progressPaint.strokeWidth = progressWidth
    }
}